#include "udp_wp_client.h"
#ifdef WIN32
#define usleep(x) Sleep(x)
#endif
#include "business_def.h"
#include "Log.h"
//acl-json
#include "acl_cpp/stdlib/string.hpp"
#include "acl_cpp/stdlib/json.hpp"
//
#include "strchange.h"

UdpWPClient::UdpWPClient(std::string paddr/*="127.0.0.1"*/,int pport/*=60005*/
    ,std::string laddr/*="127.0.0.1"*/,int lport/*=0*/)
    : running(true)
	, aliyunEvent(false)
	, queueforwar(QueueDataSingle<EventForWaring>::getInstance())
	, to_aliyun_event_queue(QueueDataSingle<JsonEvent>::getInstance())
{
    acl_lib_init();
    char  local[64]={0}, peer[64]={0};
	snprintf(local, sizeof(local), "%s:%d",laddr.c_str(),lport);
    local_addr = std::string(local);
    snprintf(peer, sizeof(peer), "%s:%d",paddr.c_str(),pport);
    peer_addr = std::string(peer);
    BusinessDef* pbd = BusinessDef::getInstance();
	aliyunEvent = pbd->getAliyunIOFunc();
	area_desc = pbd->getAreaInfo().areaDesc;
}

UdpWPClient::~UdpWPClient()
{
    running = false;
}

void* UdpWPClient::run()
{
    ACL_VSTREAM *stream = acl_vstream_bind(local_addr.c_str(), 2, 0);  /* 绑定 UDP 套接口 */
    if (stream == NULL) {
		CLogger::createInstance()->Log(MsgError,"acl_vstream_bind %s error %s in UdpWPClient::run()",
			local_addr.c_str(), acl_last_serror());
		return NULL;
	}
    printf("bind udp addr %s ok\r\n", local_addr.c_str());
    //
    acl_vstream_set_peer(stream, peer_addr.c_str());
	ACL_VSTREAM_SET_RWTIMO(stream, 1);

    char  buf[512] = {0};
    int ret = 0, dlen=0;
	while (running)
    {
        dlen = getBuf(buf,512);
        if(dlen>0)
        {
            // printf("getBuf sucess[%d]:%s\n",dlen,(char*)buf);
            ret = acl_vstream_write(stream, buf, dlen);
            if (ret == ACL_VSTREAM_EOF) {
                printf("acl_vtream_write error %s\r\n",
                    acl_last_serror());
                //重置udp
                acl_vstream_close(stream);
                stream = acl_vstream_bind(local_addr.c_str(), 2, 0);  /* 绑定 UDP 套接口 */
                if (stream == NULL) 
                {
                    CLogger::createInstance()->Log(MsgError,"acl_vstream_bind %s error %s in UdpWPClient::run()",
                        local_addr.c_str(), acl_last_serror());
                    break;
                }
            }
            // else{
            //     //
            //     printf("acl_vtream_write sucess:\n%s\n",(char*)buf);
            // }
        }
        usleep(10);
    }
    
    acl_vstream_close(stream);
    return NULL;
}

int UdpWPClient::getBuf(char* buf, int size)
{
    int ret = 0;
	
	EventForWaring efw;
    if (queueforwar->pop(efw)) 
    {
        /*
        *3==efw.send,do email msg log
        *2==efw.send,do msg log
        *1==efw.send,do log
        */
        efw.forEvtDesc();
        efw.forLevelDesc();
        efw.forWayDesc();	
        //   
        if (aliyunEvent) {
            //事件将推送到阿里云物联网平台
            JsonEvent item(efw.execTime
                , efw.taskDesc
                , efw.desc
                , efw.levelDesc
                , area_desc
                , efw.devDesc
                , efw.pDesc
                , efw.valDesc);
            to_aliyun_event_queue->add(item);
        }
        //保持日志输出,即使没有告警推送服务也能查询历史日志
        if (efw.send_ >= AlarmForLog)
        {
            char buf_log[512] = { 0 };
            sprintf(buf_log, "Time(%s),EventType(%d),EventLevel(%d),EventWay(%d)"
                ",EventDesc(%s),LevelDesc(%s),WayDesc(%s),Comment:%s"
                , efw.execTime.c_str()
                , static_cast<int>(efw.type), static_cast<int>(efw.grade), static_cast<int>(efw.send_)
                , efw.desc.c_str(),efw.levelDesc.c_str(),efw.wayDesc.c_str()
                ,efw.Comment.c_str());
            #ifdef WIN32
            std::string buf_str_log = std::string(buf_log);
			buf_str_log = UTF_82ASCII(buf_str_log);
            CLogger::createInstance()->Log(MsgInfo, "%s", buf_str_log.c_str());
            #else
            CLogger::createInstance()->Log(MsgInfo, "%s", buf_log);
            #endif
        }
        //生成告警信息的json格式
        ret = getJSonBuf(efw,buf,size);   
    }
	return ret;  
}

int UdpWPClient::getJSonBuf(EventForWaring efw,char* buf, int size)
{
    int ret = 0;
    acl::json json;
    acl::json_node& root = json.get_root();
    acl::json_node *node0, *node1, *node2, *node3, *node4, *node5, *node6, *node7, *node8, *node9;
    node0 = &root;
    //
    char buf_node[64] = { 0 };
    sprintf(buf_node, "%u", efw.send_);
    node1 = &json.create_node("send", buf_node);
    node0->add_child(node1);
    //
    node2 = &json.create_node("ETime", efw.execTime.c_str());
    node0->add_child(node2);
    //
    node3 = &json.create_node("ADesc", area_desc.c_str());
    node0->add_child(node3);
    //
    node4 = &json.create_node("EType", efw.desc.c_str());
    node0->add_child(node4);
    //
    node5 = &json.create_node("ELevel", efw.levelDesc.c_str());
    node0->add_child(node5);
    //
    node6 = &json.create_node("TaskID", efw.taskDesc.c_str());
    node0->add_child(node6);
    //
    node7 = &json.create_node("dev_desc", efw.devDesc.c_str());
    node0->add_child(node7);
    //
    node8 = &json.create_node("ponit_desc", efw.pDesc.c_str());
    node0->add_child(node8);
    //
    node9 = &json.create_node("ValDesc", efw.valDesc.c_str());
    node0->add_child(node9);
    acl::string aclbuf;
    try {
        json.build_json(aclbuf);

        if (aclbuf[aclbuf.length() - 1] == '\n') 
        {
            aclbuf += "\r";
        }else {
            aclbuf += "\n\r";
        }
        // printf("aclbuf:%s",(char*)aclbuf.c_str());
        strncpy(buf,(const char*)aclbuf.c_str(), static_cast<int>(aclbuf.length()));
        ret = static_cast<int>(aclbuf.length());
    }
    catch (...) 
    {
        CLogger::createInstance()->Log(MsgError,
            "JsonSocketWD for send data writing and json.build_json Exception"
            ",[%s %s %d]!"
            , __FILE__, __FUNCTION__, __LINE__);
    }
    return ret;
}